#include <iostream>
#include <conio.h>

#include <tisudshl.h>
#include "CmdHelper.h"
#include "Listener.h"
#include "ICCallBack.h"

#define _WIN32_WINNT 0x0500
// Specify the number of buffers to be used.
#define NUM_BUFFERS 10

using namespace _DSHOWLIB_NAMESPACE;

void runGrabber(std::string savefilename)
{
	DShowLib::InitLibrary();

	atexit(ExitLibrary);

	Grabber grabber;

	// Create the GrabberListener object.
	// CListener is derived from GrabberListener.
	CListener *pListener = new CListener();

	if (!setupDeviceFromFile(grabber))
	{
		return;
	}

	// Assign the number of buffers to the cListener object.
	pListener->setBufferSize(NUM_BUFFERS);

	// Enable the overlay bitmap to display the frame counter in the live video.
	grabber.getOverlay()->setEnable(true);

	// Register the pListener object for the frame ready and 
	// the overlay callback event.
	grabber.addListener(pListener, GrabberListener::eFRAMEREADY |
		GrabberListener::eOVERLAYCALLBACK);


	// Create a FrameTypeInfoArray data structure describing the allowed color formats.
	FrameTypeInfoArray acceptedTypes = FrameTypeInfoArray::createRGBArray();

	// Create the frame handler sink
	//smart_ptr<FrameHandlerSink> pSink = FrameHandlerSink::create( acceptedTypes, NUM_BUFFERS );

	tCodecListPtr pCodecs = Codec::getAvailableCodecs();

	// Create an MediaStreamSink to record an AVI file with the selected CoDec
	// using 0 endcoder: DV video encoder
	tMediaStreamSinkPtr pSink = MediaStreamSink::create(
		MediaStreamContainer::create(MSC_AviContainer), pCodecs->at(0));

	// Set the filename.
	pSink->setFilename(savefilename);

	// The sink is initially paused, so that no video data is written to the file.
	pSink->setSinkMode(GrabberSinkType::ePAUSE);

	// Set pSink as the current sink.
	grabber.setSinkType(pSink);

	// Start the live mode. The live video will be displayed but no images will be written
	// to the AVI file because pSink is in pause mode.
	if (!grabber.startLive(true))
	{
		std::cerr << grabber.getLastError().toString() << std::endl;
		return;
	}

	//std::cout << "Press [enter] to start capturing!";
	//std::cin.get();

	// Start the sink. The image stream is written to the AVI file.
	pSink->setSinkMode(GrabberSinkType::eRUN);

	std::cout << "Video recording started." << std::endl;
	std::cout << "Press [enter] to stop capturing!";
	std::cin.get();

	// Pause the sink. This stops writing the image stream to the AVI file.
	// A subsequent call to setSinkMode with GrabberSinkType::eRUN as the
	// parameter would restart AVI recording.
	pSink->setSinkMode(GrabberSinkType::ePAUSE);

	std::cout << "Video recording stopped." << std::endl;

	// Stop the live mode. This stops writing images to the AVI file if the mode is not
	// GrabberSinkType::ePAUSE. The AVI file is closed.
	grabber.stopLive();
	grabber.removeListener(pListener);

	// Now, it must be checked whether the CListener object has been unregistered
	// for all events.
	while (grabber.isListenerRegistered(pListener))
	{
		Sleep(0); // Wait and give pending callbacks a chance to complete.
	}

	// Now, the application can be sure that no callback methods of pListener
	// will be called anymore. It is now safe to delete pListener.
	delete pListener;

	std::cout << "Press any key to continue!" << std::endl;
	std::cin.get();

	return;
}